#ifndef JPROCESS_H
#define JPROCESS_H
/*
	创建子进程执行一个函数或其他可执行文件
	子进程的 stdin stdout stderr 被重定向到府进程（此类）

	××注：子进程执如果用来执行函数，那么他会继承父进程的所有资源
*/
#include <JXQCore/JStringList>
#include <JXQIO/JAbstractIO>
#include <climits>

namespace JXQ
{

class JProcessPrivate;

class JXQLIB_EXPORT JProcess : public JAbstractIO
{
	J_MESSAGE(finished, int)

public:
	JProcess();
	~JProcess();

public:
	enum: int
	{
		ProcessCrashed = INT_MAX - 0, //子进程崩溃返回
		WaitTimeOut    = INT_MAX - 1  //waitFinished超时返回
	};
	using ProcessMain = std::function<int(const JStringList &args)>;

	JHandle start(const JString &fileName, JStringList args = JStringList());
	JHandle start(ProcessMain &&processMain, const JStringList &args = JStringList());

	int waitFinished(int msecs = -1); //超时返回WaitTimeOut
	JHandle detach();

	struct Result
	{
		int ret;
		JString stdOut;
		JString stdError;
	};
	// 阻塞调用
	static Result execute(const JString &fileName, const JStringList &args = JStringList(),
						  int msecs = -1, bool timeoutKill = true);

	static Result execute(ProcessMain &&processMain, const JStringList &args = JStringList(),
						  int msecs = -1, bool timeoutKill = true);

public:
	enum State { Running, Finished }; //新建的对象在开始前的状态也是Finished
	State state() const;

	enum Channel { StdOut, StdError };
	void setReadChannel(Channel channel); //default stdout
	Channel readChannel();

public:
	JString readStdOut();
	JString readStdError();
	int returnCode() const;

public:
	JHandle handle() const;
	bool kill(bool force = false);
	static bool kill(JHandle handle, bool force = false);

public:
	void setBufferMode(BufferMode mode) override;
	void setBufferSize(int64_t size) override;

public:
	int64_t bytesAvailable() const override;
	int64_t size() const override; //缓冲区大小
	void flush() override;

protected:
	int64_t virtualRead(int64_t bufSize, void *buffer) override;
	int64_t virtualWrite(int64_t bufSize, const void *buffer) override;

private:
	J_DECLARE_PRIVATE(JProcess)
	J_DISABLE_COPY(JProcess)
};

} //namespace JXQ


#endif //JPROCESS_H
